/**********************************************
 * 
 * File Name				:	DateUtil.java
 * 
 * Last Changed Date		: 	$Date: 2009-08-01 11:12:53 +0800 (星期六, 01 八月 2009) $
 * 
 * Last Changed Revision	:	$Revision: 86 $
 * 
 * Last Changed Author		:	$Author: cfanboy $
 * 
 * File Header URL			:	$HeadURL: svn://www.svnhost.cn/Busi-Building/code/branch/src/com/busibuilding/utils/DateUtils.java $
 * 
 * ********************************************
 */

package com.busibuilding.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.sql.Date;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * Class Name: DateUtil.java 
 * Description: The date utils
 * @author: YU Zhipeng
 * @version: 1.0
 * @since: 1.0
 * Date: 2009-07-09
 */
public class DateUtils {
	protected static final Logger logger = LogManager
			.getLogger(DateUtils.class);

	/**
	 * Get the current date
	 * @return java.sql.Date
	 */
	public static Date getCurrentDate() {
		return new Date(System.currentTimeMillis());
	}

	/**
	 * Get the current timestamp
	 * @return Timestamp
	 */
	public static Timestamp getCurrentTimestamp() {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * Return the system time pattern
	 * @return String
	 */
	public static String getSystemTimePattern() {
		return "HH:mm";
	}

	/**
	 * Parse the String to java.sql.Date matched pattern
	 * @param str
	 * @param pattern
	 * @return
	 * @throws Exception
	 */
	public static Date parseDate(String str, String pattern) throws Exception {
		if (str == null || str.equals(""))
			return null;

		Date dt = null;
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		dtFmt.setLenient(false);
		try {
			dt = new Date(dtFmt.parse(str).getTime());
		} catch (Exception ex) {
			logger.error("Parser Exception: Invalid Date or pattern!");
			throw ex;
		}
		return dt;
	}

	/**
	 * Parse the timestamp to java.sql.Date
	 * @param time
	 * @return java.sql.Date
	 */
	public static Date parseDate(Timestamp time) {
		if (time == null)
			return null;

		return new Date(time.getTime());
	}

	/**
	 * Parse the String to Timestamp matched pattern
	 * @param str
	 * @param pattern
	 * @return Timestamp
	 * @throws Exception
	 */
	public static Timestamp parseTimestamp(String str, String pattern)
			throws Exception {
		if (str == null || str.equals(""))
			return null;

		Timestamp dt = null;
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		try {
			dt = new Timestamp(dtFmt.parse(str).getTime());
		} catch (Exception ex) {
			logger.error("Parser Exception: Invalid Timestamp or pattern!");
			throw ex;
		}
		return dt;
	}

	/**
	 * Parse the java.sql.Date to timestamp
	 * @param date
	 * @return Timestamp
	 */
	public static Timestamp parseTimestamp(Date date) {
		if (date == null)
			return null;

		return new Timestamp(date.getTime());
	}
	
	/**
	 * Parse the Sting to java.util.Date matched pattern 
	 * @param str
	 * @param pattern
	 * @return java.util.Date
	 * @throws Exception
	 */
	public static java.util.Date parseUtilDate(String str, String pattern)
			throws Exception {
		if (str == null || str.equals(""))
			return null;

		java.util.Date dt = null;
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		try {
			dt = new java.util.Date(dtFmt.parse(str).getTime());
		} catch (Exception ex) {
			logger.error("Parser Exception: Invalid Date or pattern!");
			throw ex;
		}
		return dt;
	}

	/**
	 * Format the time part of java.sql.Date that passed in to String
	 * @param date
	 * @return String
	 */
	public static String toTimeString(Date date) {
		String pattern = getSystemTimePattern();
		return toString(date, pattern);
	}

	/**
	 * Format the time part of timestamp that passed in to String
	 * @param timestamp
	 * @return String
	 */
	public static String toTimeString(Timestamp timestamp) {
		String pattern = getSystemTimePattern();
		return toString(timestamp, pattern);
	}

	/**
	 * Format the long to datetime String 
	 * @param datetime
	 * @param pattern
	 * @return String
	 */
	public static String toString(long datetime, String pattern) {
		Date date = new Date(datetime);
		return toString(date, pattern);
	}
	
	/**
	 * Format the java.sql.Date to String
	 * @param date
	 * @param pattern
	 * @return String
	 */
	public static String toString(Date date, String pattern) {
		if (date == null)
			return "";
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		return dtFmt.format(date);
	}

	/**
	 * Format the java.util.Date to String
	 * @param date
	 * @param pattern
	 * @return String
	 */
	public static String toString(java.util.Date date, String pattern) {
		if (date == null)
			return "";
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		return dtFmt.format(date);
	}

	/**
	 * Format the timestamp to String
	 * @param timestamp
	 * @param pattern
	 * @return String
	 */
	public static String toString(Timestamp timestamp, String pattern) {
		if (timestamp == null)
			return "";
		DateFormat dtFmt = new SimpleDateFormat(pattern);
		return dtFmt.format(timestamp);
	}

	/**
	 * Add the date
	 * @param datetime
	 * @param datepart
	 * @param number
	 * @return java.sql.Date
	 */
	public static Date add(Date datetime, int datepart, int number) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datetime);
		calendar.add(datepart, number);
		return new Date(calendar.getTimeInMillis());
	}

	/**
	 * Add the date
	 * @param datetime
	 * @param datepart
	 * @param number
	 * @return Timestamp
	 */
	public static Timestamp add(Timestamp datetime, int datepart, int number) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(datetime.getTime());
		calendar.add(datepart, number);
		return new Timestamp(calendar.getTimeInMillis());
	}

	/**
	 * Roll the datetime
	 * @param datetime
	 * @param datepart
	 * @param number
	 * @return java.sql.Date
	 */
	public static Date roll(Date datetime, int datepart, int number) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datetime);
		calendar.roll(datepart, number);
		return new Date(calendar.getTimeInMillis());
	}

	/**
	 * Roll the datetime
	 * @param datetime
	 * @param datepart
	 * @param number
	 * @return java.util.Date
	 */
	public static java.util.Date roll(java.util.Date datetime, int datepart,
			int number) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datetime);
		calendar.roll(datepart, number);
		return new java.util.Date(calendar.getTimeInMillis());
	}

	/**
	 * Roll the datetime
	 * @param datetime
	 * @param datepart
	 * @param number
	 * @return Timestamp
	 */
	public static Timestamp roll(Timestamp datetime, int datepart, int number) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(datetime.getTime());
		calendar.roll(datepart, number);
		return new Timestamp(calendar.getTimeInMillis());
	}


	/**
	 * Get the time part
	 * @param datetime
	 * @param datepart
	 * @return
	 */
	public static int getDateTimePart(java.util.Date datetime, int datepart) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(datetime.getTime());
		return cal.get(datepart);
	}

	/**
	 * Set the time part
	 * @param datetime
	 * @param datepart
	 * @param value
	 */
	public static void setDateTimePart(java.util.Date datetime, int datepart,
			int value) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(datetime.getTime());
		cal.set(datepart, value);
		datetime.setTime(cal.getTimeInMillis());
	}

	/**
	 * Validate the date passed in is after than today
	 * @param date
	 * @return boolean
	 */
	public static boolean isAfterToday(Date date) {
		if (date == null)
			return false;

		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(date.getTime());
		Calendar now = Calendar.getInstance();

		if (cal.get(Calendar.YEAR) > now.get(Calendar.YEAR)
				|| (cal.get(Calendar.YEAR) == now.get(Calendar.YEAR) && cal
						.get(Calendar.DAY_OF_YEAR) > now
						.get(Calendar.DAY_OF_YEAR))) {
			return true;
		} else
			return false;
	}

	/**
	 * Validate the date passed in is before than today
	 * @param date
	 * @return boolean
	 */
	public static boolean isBeforeToday(Date date) {
		if (date == null)
			return false;

		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(date.getTime());
		Calendar now = Calendar.getInstance();

		if (cal.get(Calendar.YEAR) < now.get(Calendar.YEAR)
				|| (cal.get(Calendar.YEAR) == now.get(Calendar.YEAR) && cal
						.get(Calendar.DAY_OF_YEAR) < now
						.get(Calendar.DAY_OF_YEAR))) {
			return true;
		} else
			return false;
	}

	/**
	 * Validate the datetime passed in is after that now
	 * @param time
	 * @return boolean
	 */
	public static boolean isAfterNow(Timestamp time) {
		if (time == null)
			return false;

		if (time.after(new Timestamp(System.currentTimeMillis())))
			return true;
		else
			return false;
	}

	/**
	 * Validate the datetime passed in is before than now
	 * @param time
	 * @return boolean
	 */
	public static boolean isBeforeNow(Timestamp time) {
		if (time == null)
			return false;

		if (time.before(new Timestamp(System.currentTimeMillis())))
			return true;
		else
			return false;
	}

	/**
	 * Validate the year is or not leap year.
	 * @param date
	 * @return boolean ture - leap year
	 */
	public static boolean isLeapYear(java.util.Date date) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTimeInMillis(date.getTime());
		return cal.isLeapYear(cal.get(Calendar.YEAR));
	}

	/**
	 * Compare two date
	 * @param headDate
	 * @param tailDate
	 * @return long The difference value of these two date.
	 */
	public static long compare(java.util.Date headDate, java.util.Date tailDate) {
		return tailDate.getTime() - headDate.getTime();
	}

	/**
	 * Get the duration date between start and end date that passed in
	 * @param start
	 * @param end
	 * @return String
	 * @throws Exception
	 */
	public static String getDurationDate(java.util.Date start,
			java.util.Date end) throws Exception {
		if (start == null || end == null || compare(start, end) < 0)
			return null;

		Calendar startCalendar = Calendar.getInstance();
		startCalendar.setTime(start);
		startCalendar.set(Calendar.HOUR_OF_DAY, 0);
		startCalendar.set(Calendar.MINUTE, 0);
		startCalendar.set(Calendar.SECOND, 0);
		startCalendar.set(Calendar.MILLISECOND, 0);
		Calendar endCalendar = Calendar.getInstance();
		endCalendar.setTime(end);
		endCalendar.set(Calendar.HOUR_OF_DAY, 0);
		endCalendar.set(Calendar.MINUTE, 0);
		endCalendar.set(Calendar.SECOND, 0);
		endCalendar.set(Calendar.MILLISECOND, 0);

		int durationYear = 0;
		int durationMonth = 0;
		int durationDay = 0;

		// Compute Year Value
		startCalendar.add(Calendar.YEAR, 1);
		while (startCalendar.before(endCalendar)
				|| SameDay(startCalendar, endCalendar)) {
			durationYear++;
			startCalendar.add(Calendar.YEAR, 1);
		}
		startCalendar.add(Calendar.YEAR, -1);

		// Compute Month Value
		startCalendar.add(Calendar.MONTH, 1);
		while (startCalendar.before(endCalendar)
				|| SameDay(startCalendar, endCalendar)) {
			durationMonth++;
			startCalendar.add(Calendar.MONTH, 1);
		}
		startCalendar.add(Calendar.MONTH, -1);

		// Compute Day Value
		startCalendar.add(Calendar.DAY_OF_YEAR, 1);
		durationDay++;
		while (startCalendar.before(endCalendar)
				|| SameDay(startCalendar, endCalendar)) {
			durationDay++;
			startCalendar.add(Calendar.DAY_OF_YEAR, 1);
		}

		StringBuffer duration = new StringBuffer();
		duration.append(durationYear < 10 ? "0" + durationYear : ""
				+ durationYear);
		duration.append(durationMonth < 10 ? "0" + durationMonth : ""
				+ durationMonth);
		duration
				.append(durationDay < 10 ? "0" + durationDay : "" + durationDay);
		return duration.toString();
	}

	private static boolean SameDay(Calendar startCalendar, Calendar endCalendar) {
		if (startCalendar.get(Calendar.YEAR) == endCalendar.get(Calendar.YEAR)
				&& startCalendar.get(Calendar.MONTH) == endCalendar
						.get(Calendar.MONTH)
				&& startCalendar.get(Calendar.DAY_OF_MONTH) == endCalendar
						.get(Calendar.DAY_OF_MONTH)) {
			return true;
		} else {
			return false;
		}
	}
}
